﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Web.Mvc;
using System.Web.Routing;
using UIShell.OSGi;
using UIShell.OSGi.Loader;

namespace UIShell.OSGI.Mvc
{
    public class BundleRuntimeControllerFactory : DefaultControllerFactory
    {
        public static HashSet<string> Namespaces = new HashSet<string>();
        public BundleRuntimeControllerFactory()
        {

        }
        public BundleRuntimeControllerFactory(Assembly shellAssembly)
        {
            Register(shellAssembly);
        }

        protected override Type GetControllerType(RequestContext requestContext, string controllerName)
        {
            string symbolicName = requestContext.RouteData.GetPluginSymbolicName();

            var controllerType = ControllerTypeCache.GetControllerType(symbolicName, controllerName);
            if (controllerType != null) return controllerType;

            if (symbolicName != null)
            {
                var controllerTypeName = controllerName + "Controller";
                var runtimeService = BundleRuntime.Instance.GetFirstOrDefaultService<IRuntimeService>();
                var assemblies = runtimeService.LoadBundleAssembly(symbolicName);

                foreach (var assembly in assemblies)
                {
                    foreach (var type in assembly.GetTypes())
                    {
                        if (!type.Name.ToLower().Contains(controllerTypeName.ToLower()) ||
                            !typeof (IController).IsAssignableFrom(type)) continue;

                        ControllerTypeCache.AddControllerType(symbolicName, controllerName, type);
                        return type;
                    }
                }
                return null;
            }

            requestContext.RouteData.DataTokens["Namespaces"] = Namespaces;
            return base.GetControllerType(requestContext, controllerName);
        }

        public static void Register(Assembly assembly)
        {
            foreach (var type in assembly.GetExportedTypes())
            {
                if (!type.IsAbstract && typeof(IController).IsAssignableFrom(type))
                {
                    if (type.Namespace != null)
                    {
                        Namespaces.Add(type.Namespace);
                    }
                }
            }
        }
    }
}
